/**
* Componente Curricular: Módulo Integrado de Programação
* Autores: João Paulo Santos Sena e Marcelo Bião Cerqueira
* Data: 14/09/2013
*
* Declaro que este código foi elaborado em dupla de forma cooperativa e
* não contém nenhum trecho de código de outro colega ou de outro autor, 
* tais como provindos de livros e apostilas, e páginas ou documentos 
* eletrônicos da Internet. Qualquer trecho de código de outra autoria que
* uma citação para o  não a minha está destacado com  autor e a fonte do
* código, e estou ciente que estes trechos não serão considerados para fins
* de avaliação. Alguns trechos do código podem coincidir com de outros
* colegas pois estes foram discutidos em sessões tutorias.
*/

package util;

import forcetower.Carta;
import forcetower.Jogador;

/**
 * Lista Encadeada do Aplicativo
 * @author João Paulo Santos Sena e Marcelo Bião Cerqueira
 * @since 14/09/2013
 * @version 2.0
 */
public class ListaEncadeada implements ILista{
	private NoLink primeiro;

	@Override
	public boolean estaVazia() {
		if (primeiro == null){
			return true;
		}
		return false;
	}

	@Override
	public int tamanho() {
		NoLink aux = primeiro;
		if (primeiro == null) {
			return 0;
		}
		int tamanhoNew = 1;
		while (aux.getProximo() != null) {
			aux = aux.getProximo();
			tamanhoNew++;
		}
		
		return tamanhoNew;
	}

	@Override
	public void insereInicio(Object o) {
		if (primeiro == null){
			NoLink novo = new NoLink();
			novo.setConteudo(o);
			novo.setProximo(null);
			primeiro = novo;
		}
		
		else {
			NoLink novo = new NoLink();
			novo.setConteudo(o);
			novo.setProximo(primeiro);
			primeiro = novo;
		}
	}

	@Override
	public void insereFinal(Object o) {
		if (primeiro == null) {
			this.insereInicio(o);
		}
		else {
			NoLink novo = new NoLink();
			novo.setConteudo(o);
			novo.setProximo(null);
			
			NoLink aux = primeiro;
			while (aux.getProximo() != null) {
				aux = aux.getProximo();
			}
			aux.setProximo(novo);
		}
	}

	@Override
	public Object removeInicio() {
		if (primeiro != null){
			NoLink aux = primeiro;
			primeiro = primeiro.getProximo();
			aux.setProximo(null);
			return aux.getConteudo();
		}
		return null;
	}

	@Override
	public Object removeUltimo() {
		NoLink first = primeiro;
		if (first.getProximo() == null){
			Object obj = this.removeInicio();
			return obj;
		}
		
		else if (first.getProximo() != null) {
			NoLink aux = primeiro.getProximo();
			NoLink anterior = primeiro;
			
			while (aux.getProximo() != null) {
				anterior = aux;
				aux = aux.getProximo();
			}
			anterior.setProximo(null);
			return aux.getConteudo();
		}
		return null;
	}

	@Override
	public Object recupera(int index) {
		if (this.tamanho() > 0 && index <= this.tamanho()) {
			NoLink aux = primeiro;
			for (int i = 0; i < index; i++) {
				aux = aux.getProximo();
			}
			return aux.getConteudo();
		}
		return null;
	}

	@Override
	public Iterador iterador() {
		Iterador it = new Iterator(primeiro);
		return it;
	}

	/**
	 * Metodo utilizado para a construção do Iterador
	 * 
	 * Exemplo de uso:
     * NoLink primeiro = lista.getPrimeiro();
     * 
	 * @return Retorna uma copia da referencia do primeiro elemento da ListaEncadeada
	 */
	public NoLink getPrimeiro() {
		return primeiro;
	}
	
	/**
	 * Metodo responsavel pela busca de um paciente pelo seu codigo
	 * 
	 * Exemplo de uso:
     * Paciente paciente = lista.recuperaCodigoPaciente(2);
     * 
	 * @param codigo Codigo do paciente a ser procurado
	 * @return Retorna a copia da referencia do Paciente encontrado, ou null caso o paciente não foi encontrado 
	 */
	public Object recuperaJogador(String nome) {
		NoLink aux = primeiro;
		for (int i = 0; i < this.tamanho(); i++) {
			Jogador temp = (Jogador)aux.getConteudo();
			if (temp.getNome().equals(nome)) {
				return aux.getConteudo();
			}
			aux = aux.getProximo();
		}
		return null;
	}
	
	public Object recuperaCarta(int numOrdenado) {
		NoLink aux = primeiro;
		for (int i = 0; i < this.tamanho(); i++) {
			Carta temp = (Carta)aux.getConteudo();
			if (temp.getNumeroOrdenado() == numOrdenado) {
				return aux.getConteudo();
			}
			aux = aux.getProximo();
		}
		return null;
	}
	
	/**
	* Metodo responsavel por remover um objeto a lista a partir de um objeto passado por parametro
	* 
	* Exemplo de uso:
    * lista.remove(Objeto);
	* 
	* @param retirar Referencia para o objeto que será retirado da lista
	* */
	public void remove (Object retirar){
		if (primeiro.getConteudo().equals(retirar)) {
			this.removeInicio();
		}
		else {
			NoLink aux = primeiro.getProximo();
			NoLink ant = primeiro;
			
			while (!aux.getConteudo().equals(retirar) && aux != null) {
				ant = aux;
				aux = aux.getProximo();
			}
			if (aux == null)
			{
				System.out.println ("Objeto não encontrado!");
			}
			
			ant.setProximo(aux.getProximo());
			aux.setProximo(null);
		}
	}
	
	public void organizarLista (ListaEncadeada desarrumada, ListaEncadeada arrumada) {
		ListaEncadeada aux = new ListaEncadeada();
		
		if (desarrumada.estaVazia()) {
			System.out.println("Vazia");
		}
		
		else {
			Iterador it = desarrumada.iterador();
			
			while (it.temProximo()) {
				Carta temp = (Carta)desarrumada.removeInicio();
				aux.insereFinal(temp);
				arrumada.insereOrdenado(temp);
			}
			
			desarrumada = aux;
		}
	}

	public void insereOrdenado(Carta temp) {
		NoLink novo = new NoLink();
		novo.setConteudo(temp);
		novo.setProximo(null);
		
		if (primeiro == null) {
			primeiro = novo;
		}
		
		NoLink atual = primeiro;
		NoLink anterior = null;
		
		while ( ((Carta) atual.getConteudo()).getNumeroOrdenado() < temp.getNumeroOrdenado() && atual != null) {
			anterior = atual;
			atual = atual.getProximo();
		}
		
		if (anterior == null) {
			primeiro = novo;
		}
		
		else { 
			anterior.setProximo(novo);
		}
		
		novo.setProximo(atual);
	}
}
